package com.summer.filesync.manager.service;

import com.summer.filesync.database.dao.FileMetadataDAO;
import com.summer.filesync.model.manager.*;
import com.summer.filesync.util.Logger;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/** 文件统计服务 提供文件系统统计和报告功能 */
public class FileStatisticsService {
  private static final Logger logger = Logger.getLogger(FileStatisticsService.class);

  private final FileMetadataDAO fileMetadataDAO;
  private final ExecutorService statsExecutor;
  private final Map<String, FileSystemStatistics> statisticsCache;

  public FileStatisticsService(FileMetadataDAO fileMetadataDAO) {
    this.fileMetadataDAO = fileMetadataDAO;
    this.statsExecutor = Executors.newFixedThreadPool(2);
    this.statisticsCache = new ConcurrentHashMap<>();
  }

  /** 生成文件系统统计信息 */
  public CompletableFuture<FileSystemStatistics> generateFileSystemStatistics(
      List<String> directories) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("开始生成文件系统统计信息");

          FileSystemStatistics stats = new FileSystemStatistics();
          stats.setLastUpdated(LocalDateTime.now());

          Map<String, Integer> fileTypeCount = new HashMap<>();
          Map<String, Long> fileTypeSize = new HashMap<>();
          long totalFiles = 0;
          long totalDirectories = 0;
          long totalSize = 0;
          long largestFileSize = 0;

          try {
            for (String directory : directories) {
              Files.walkFileTree(
                  Paths.get(directory),
                  new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                      if (attrs.isRegularFile()) {
                        // 更新统计数据
                        stats.setTotalFiles(stats.getTotalFiles() + 1);
                        stats.setTotalSize(stats.getTotalSize() + attrs.size());

                        // 最大文件
                        if (attrs.size() > stats.getLargestFileSize()) {
                          stats.setLargestFileSize(attrs.size());
                        }

                        // 文件类型统计
                        String fileName = file.getFileName().toString();
                        String extension = getFileExtension(fileName);
                        fileTypeCount.put(extension, fileTypeCount.getOrDefault(extension, 0) + 1);
                        fileTypeSize.put(
                            extension, fileTypeSize.getOrDefault(extension, 0L) + attrs.size());

                      } else if (attrs.isDirectory()) {
                        stats.setTotalDirectories(stats.getTotalDirectories() + 1);
                      }

                      return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
                      stats.setTotalDirectories(stats.getTotalDirectories() + 1);
                      return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFileFailed(Path file, IOException exc) {
                      return FileVisitResult.CONTINUE;
                    }
                  });
            }

            // 计算平均文件大小
            if (stats.getTotalFiles() > 0) {
              stats.setAverageFileSize(stats.getTotalSize() / stats.getTotalFiles());
            }

            // 设置文件类型分布
            stats.setFileTypeDistribution(fileTypeCount);
            stats.setSizeDistribution(fileTypeSize);

            // 缓存结果
            String cacheKey = String.join(",", directories);
            statisticsCache.put(cacheKey, stats);

            logger.info(
                "文件系统统计完成: "
                    + stats.getTotalFiles()
                    + " 文件, "
                    + stats.getTotalDirectories()
                    + " 目录");

          } catch (Exception e) {
            logger.error("生成文件系统统计失败", e);
          }

          return stats;
        },
        statsExecutor);
  }

  /** 生成目录统计信息 */
  public CompletableFuture<DirectoryStatistics> generateDirectoryStatistics(String directoryPath) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("生成目录统计: " + directoryPath);

          DirectoryStatistics dirStats = new DirectoryStatistics(directoryPath);

          try {
            Path directory = Paths.get(directoryPath);

            Files.list(directory)
                .forEach(
                    path -> {
                      try {
                        BasicFileAttributes attrs =
                            Files.readAttributes(path, BasicFileAttributes.class);

                        if (attrs.isRegularFile()) {
                          dirStats.setFileCount(dirStats.getFileCount() + 1);
                          dirStats.setTotalSize(dirStats.getTotalSize() + attrs.size());

                          if (attrs.size() > dirStats.getLargestFileSize()) {
                            dirStats.setLargestFileSize(attrs.size());
                            dirStats.setLargestFileName(path.getFileName().toString());
                          }

                        } else if (attrs.isDirectory()) {
                          dirStats.setSubdirectoryCount(dirStats.getSubdirectoryCount() + 1);
                        }

                      } catch (Exception e) {
                        // 忽略单个文件错误
                      }
                    });

            if (dirStats.getFileCount() > 0) {
              dirStats.setAverageFileSize(dirStats.getTotalSize() / dirStats.getFileCount());
            }

          } catch (Exception e) {
            logger.error("生成目录统计失败: " + directoryPath, e);
          }

          return dirStats;
        },
        statsExecutor);
  }

  /** 生成文件活动统计 */
  public CompletableFuture<FileActivityStatistics> generateFileActivityStatistics(
      List<String> directories, int days) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("生成文件活动统计，最近 " + days + " 天");

          FileActivityStatistics activityStats = new FileActivityStatistics(days);

          LocalDateTime cutoffTime = LocalDateTime.now().minusDays(days);

          try {
            for (String directory : directories) {
              Files.walkFileTree(
                  Paths.get(directory),
                  new SimpleFileVisitor<Path>() {
                    @Override
                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
                      if (attrs.isRegularFile()) {
                        LocalDateTime modifiedTime =
                            LocalDateTime.ofInstant(
                                attrs.lastModifiedTime().toInstant(), ZoneId.systemDefault());

                        LocalDateTime createdTime =
                            LocalDateTime.ofInstant(
                                attrs.creationTime().toInstant(), ZoneId.systemDefault());

                        // 最近修改的文件
                        if (modifiedTime.isAfter(cutoffTime)) {
                          activityStats.setTotalModified(activityStats.getTotalModified() + 1);
                        }

                        // 最近创建的文件
                        if (createdTime.isAfter(cutoffTime)) {
                          activityStats.setTotalCreated(activityStats.getTotalCreated() + 1);
                        }

                        // 大文件和空文件统计（简化实现）
                        // 这些统计可以在后续版本中扩展
                      }

                      return FileVisitResult.CONTINUE;
                    }

                    @Override
                    public FileVisitResult visitFileFailed(Path file, IOException exc) {
                      return FileVisitResult.CONTINUE;
                    }
                  });
            }

          } catch (Exception e) {
            logger.error("生成文件活动统计失败", e);
          }

          return activityStats;
        },
        statsExecutor);
  }

  /** 生成存储使用报告 */
  public CompletableFuture<StorageUsageReport> generateStorageUsageReport(
      List<String> directories) {
    return CompletableFuture.supplyAsync(
        () -> {
          logger.info("生成存储使用报告");

          StorageUsageReport report = new StorageUsageReport();
          report.setGeneratedTime(LocalDateTime.now());

          Map<String, Long> directoryUsage = new HashMap<>();
          long totalUsed = 0;

          try {
            for (String directory : directories) {
              long directorySize = calculateDirectorySize(Paths.get(directory));
              directoryUsage.put(directory, directorySize);
              totalUsed += directorySize;

              // 获取磁盘总容量和可用空间（简化实现）
              try {
                FileStore store = Files.getFileStore(Paths.get(directory));
                // 简化实现，不设置这些值，因为StorageUsageReport没有这些方法
                logger.debug(
                    "磁盘空间信息 - 总容量: " + store.getTotalSpace() + ", 可用: " + store.getUsableSpace());
              } catch (Exception e) {
                // 忽略磁盘空间查询错误
              }
            }

            report.setDirectoryUsage(directoryUsage);
            // 简化实现，使用现有的方法
            logger.info("扫描的总大小: " + totalUsed + " 字节");

          } catch (Exception e) {
            logger.error("生成存储使用报告失败", e);
          }

          return report;
        },
        statsExecutor);
  }

  /** 关闭统计服务 */
  public void shutdown() {
    logger.info("文件统计服务正在关闭...");
    statsExecutor.shutdown();
    statisticsCache.clear();
  }

  /** 获取文件扩展名 */
  private String getFileExtension(String fileName) {
    int lastDot = fileName.lastIndexOf('.');
    if (lastDot > 0 && lastDot < fileName.length() - 1) {
      return fileName.substring(lastDot + 1).toLowerCase();
    }
    return "无扩展名";
  }

  /** 计算目录大小 */
  private long calculateDirectorySize(Path directory) {
    try {
      return Files.walk(directory)
          .filter(Files::isRegularFile)
          .mapToLong(
              path -> {
                try {
                  return Files.size(path);
                } catch (Exception e) {
                  return 0;
                }
              })
          .sum();
    } catch (Exception e) {
      logger.error("计算目录大小失败: " + directory, e);
      return 0;
    }
  }
}
